package com.zhiwei.msf.infra.oauth.service.impl;

import com.zhiwei.msf.infra.oauth.service.AuthorityInfoService;
import com.zhiwei.msf.infra.oauth.entity.AuthorityInfo;
import com.zhiwei.msf.infra.oauth.entity.UserInfo;
import com.zhiwei.msf.infra.oauth.service.UserInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 自定义用户认证与授权数据服务
 */
@Service
@Slf4j
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private AuthorityInfoService authorityInfoService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserInfo userInfo = userInfoService.getByUsername(username);
        if (userInfo != null) {
            List<AuthorityInfo> authorityInfoList = authorityInfoService.selectByUserId(userInfo.getUuid());
            if (CollectionUtils.isEmpty(authorityInfoList)) {
                log.warn("User:[{}] has no GrantedAuthority", username);
                return new User(userInfo.getUsername(), userInfo.getPassword(), Collections.emptyList());
            }
            List<String> authorityNameList = authorityInfoList.stream().map(AuthorityInfo::getEname).collect(Collectors.toList());
            Collection<? extends GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList(StringUtils.collectionToCommaDelimitedString(authorityNameList));
            return new User(userInfo.getUsername(), userInfo.getPassword(), authorities);
        }
        throw new UsernameNotFoundException("User:[" + username + "] is not exist");
    }
}